﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ttifa.MongoDB;

namespace Ttifa.Log
{
    public class MongoLog : ILog
    {
        private Dictionary<string, object> mProperties = new Dictionary<string, object>();

        private string _collectionName;

        public MongoLog(string name)
        {
            _collectionName = name;
        }

        private enum LogLevel
        {
            Info,
            Trace,
            Debug,
            Warn,
            Error,
            Fatal
        }

        private void WriteLog(LogLevel level, string message, Dictionary<string, object> properties, Exception ex = null)
        {
            properties.ToList().ForEach(m =>
            {
                if (m.Value == null)
                    return;

                var type = m.Value.GetType();
                if (type.IsPrimitive || type == typeof(String))
                    return;

                if (type == typeof(DateTime) || type.GetType() == typeof(DateTime?))
                    properties[m.Key] = ((DateTime)m.Value).ToString("yyyy-MM-dd HH:mm:ss.ffff");
                else
                    properties[m.Key] = JsonConvert.SerializeObject(m.Value);
            });

            var log = new LogModel
            {
                Level = level.ToString(),
                LogTime = DateTime.Now,
                Message = message,
                Details = properties
            };
            if (ex != null)
                log.Exception = ex.ToString();

            var util = new MongoDBHelper<LogModel>(this._collectionName);
            util.Insert(log);
        }

        #region "实现接口"

        public ILog SetProperties<T>(T t)
        {
            mProperties = new Dictionary<string, object>();
            var type = t.GetType();
            var properties = type.GetProperties();
            foreach (var p in properties)
            {
                mProperties.Add(p.Name, p.GetValue(t));
            }

            return this;
        }

        public ILog SetProperties(Dictionary<string, object> properties)
        {
            mProperties = properties;
            return this;
        }

        public ILog AddProperty(string key, object value)
        {
            if (mProperties == null)
                mProperties = new Dictionary<string, object>();

            if (mProperties.ContainsKey(key))
                mProperties[key] = value;
            else
                mProperties.Add(key, value);

            return this;
        }

        public void Info(string message)
        {
            WriteLog(LogLevel.Info, message, mProperties);
        }

        public void Trace(string message)
        {
            WriteLog(LogLevel.Trace, message, mProperties);
        }

        public void Debug(string message)
        {
            WriteLog(LogLevel.Debug, message, mProperties);
        }

        public void Warn(string message)
        {
            WriteLog(LogLevel.Warn, message, mProperties);
        }

        public void Error(string message, Exception ex = null)
        {
            WriteLog(LogLevel.Error, message, mProperties, ex);
        }

        public void Fatal(string message, Exception ex = null)
        {
            WriteLog(LogLevel.Fatal, message, mProperties, ex);
        }

        #endregion
    }

    public class LogModel : BaseEntity
    {
        public DateTime LogTime { get; set; }

        public string Level { get; set; }

        public string Message { get; set; }

        public string Exception { get; set; }

        public Dictionary<string, object> Details { get; set; }
    }
}
